
#include "MeshRenderer.h"
#ifdef RENDER_OPENGL
    #include <gl\GL.h>
#endif
#include "../Scene/ZDataManager.h"
#include "../Common/ZException.h"

GLOBAL_NAMESPACE_BEGIN

MeshRenderer::MeshRenderer() 
    : Renderer()
{

}

MeshRenderer::~MeshRenderer()
{

}

void MeshRenderer::beginToDraw()
{
#ifdef RENDER_OPENGL
    if (getRenderOption().translucent)
    {
        glEnable(GL_BLEND);
        //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glBlendFunc(GL_ONE, GL_ONE);
        glDisable(GL_DEPTH_TEST);
    }
#endif//WO_RENDER
}

void MeshRenderer::endDraw()
{
#ifdef RENDER_OPENGL
    glDisable(GL_BLEND);
    glEnable(GL_DEPTH_TEST);
#endif
}

void MeshRenderer::draw()
{
    MeshSpace::Mesh3D* mesh = DataManager::getSingleton().getMesh();
    if (!mesh) return;

    beginToDraw();
    // draw something
    drawMesh(mesh);
    endDraw();
}

void MeshRenderer::drawMesh(MeshSpace::Mesh3D *mesh)
{
    if (renderOpt_.strRenderMethod == _RTYPE_(RENDER_TYPE_NONE))
    {
        ;
    }
    else if (renderOpt_.strRenderMethod == _RTYPE_(RENDER_TYPE_POINTS))
    {
        drawPoints(mesh);
    }
    else if (renderOpt_.strRenderMethod == _RTYPE_(RENDER_TYPE_SOLID_FLAT))
    {
        drawSolidFlat(mesh);
    }
    else if (renderOpt_.strRenderMethod == _RTYPE_(RENDER_TYPE_SOLID_SMOOTH))
    {
        drawSolidSmooth(mesh);
    }
    else if (renderOpt_.strRenderMethod == _RTYPE_(RENDER_TYPE_VERTEX_COLOR))
    {
        drawMeshByVerticeColors(mesh);
    }
    else if (renderOpt_.strRenderMethod == _RTYPE_(RENDER_TYPE_FACE_COLOR))
    {
        drawMeshByFaceColors(mesh);
    }
}


void MeshRenderer::drawPoints(MeshSpace::Mesh3D *mesh)
{
    ZFW_EXCEPTION(Exception::ERR_NOT_IMPLEMENTED, "unsupport: drawPoints()", "MeshRenderer::drawPoints");
}

void MeshRenderer::drawSolidFlat(MeshSpace::Mesh3D *mesh)
{
#ifdef RENDER_OPENGL
    glEnable(GL_LIGHTING);
    glShadeModel(GL_FLAT);
    for (int i = 0; i<mesh->get_num_of_faces_list(); i++)
    {
        MeshSpace::HE_face* face = mesh->get_face(i);
        MeshSpace::HE_edge* edge = face->m_pedge;
        glBegin(GL_POLYGON);
        do
        {
            MeshSpace::HE_vert* v = edge->m_pvert;
            glColor4dv(v->m_color);
            glNormal3dv(v->m_vnormal);
            glVertex3dv(v->m_vpos);
            edge = edge->m_pnext;
        } while (edge != face->m_pedge);
        glEnd();
    }
#endif
}

void MeshRenderer::drawSolidSmooth(MeshSpace::Mesh3D *mesh)
{
#ifdef RENDER_OPENGL
    glEnable(GL_LIGHTING);
    glShadeModel(GL_SMOOTH);
    for (int i = 0; i<mesh->get_num_of_faces_list(); i++)
    {
        MeshSpace::HE_face* face = mesh->get_face(i);
        MeshSpace::HE_edge* edge = face->m_pedge;
        glBegin(GL_POLYGON);
        do
        {
            MeshSpace::HE_vert* v = edge->m_pvert;
            glColor4dv(v->m_color);
            glNormal3dv(v->m_vnormal);
            glVertex3dv(v->m_vpos);
            edge = edge->m_pnext;
        } while (edge != face->m_pedge);
        glEnd();
    }
#endif
}

void MeshRenderer::drawMeshByVerticeColors(MeshSpace::Mesh3D *mesh)
{
#ifdef RENDER_OPENGL
    glEnable(GL_LIGHTING);
    glShadeModel(GL_SMOOTH);
    //glShadeModel(GL_FLAT);
    for (int i = 0; i<mesh->get_num_of_faces_list(); i++)
    {
        MeshSpace::HE_face* face = mesh->get_face(i);
        MeshSpace::HE_edge* edge = face->m_pedge;
        glBegin(GL_POLYGON);
        do
        {
            MeshSpace::HE_vert* v = edge->m_pvert;
            double rgb[4];
            RenderOption::colorCoding(v->m_colorValue, rgb);
            rgb[3] = 0.7f;
            glColor3dv(rgb);
            glNormal3dv(v->m_vnormal);
            glVertex3dv(v->m_vpos);
            edge = edge->m_pnext;
        } while (edge != face->m_pedge);
        glEnd();
    }
#endif
}

void MeshRenderer::drawMeshByFaceColors(MeshSpace::Mesh3D *mesh)
{
#ifdef RENDER_OPENGL
    glEnable(GL_LIGHTING);
    glShadeModel(GL_SMOOTH);
    glShadeModel(GL_FLAT);
    for (int i = 0; i<mesh->get_num_of_faces_list(); i++)
    {
        MeshSpace::HE_face* face = mesh->get_face(i);
        MeshSpace::HE_edge* edge = face->m_pedge;
        glBegin(GL_POLYGON);
        double rgb[4];
        RenderOption::colorCoding(face->m_value, rgb);
        do
        {
            MeshSpace::HE_vert* v = edge->m_pvert;
            rgb[3] = 0.7f;
            glColor3dv(rgb);
            glNormal3dv(v->m_vnormal);
            glVertex3dv(v->m_vpos);
            edge = edge->m_pnext;
        } while (edge != face->m_pedge);
        glEnd();
    }
#endif
}

GLOBAL_NAMESPACE_END

